package com.dbflow5.query.list;

import com.dbflow5.BaseUnitTest;
import com.dbflow5.config.FlowManager;
import com.dbflow5.database.DatabaseWrapper;
import com.dbflow5.models.SimpleTestModels.SimpleModel;
import com.dbflow5.query.SQLite;

import org.junit.Test;

import java.util.function.Function;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class FlowCursorIteratorTest extends BaseUnitTest {
    @Test
    public void testCanIterateFullList() {
        final int[] count = {0};

        FlowManager.databaseForTable(SimpleModel.class, db -> {
            db.beginTransactionAsync((Function<DatabaseWrapper, Object>) databaseWrapper -> {
                for (int i = 0; i < 10; i++) {
                    FlowManager.getModelAdapter(SimpleModel.class).save(new SimpleModel(String.valueOf(i)), db);
                }
                return null;
            }).success((objectTransaction, o) -> {
                FlowCursorIterator<SimpleModel> iterator = SQLite.select().from(SimpleModel.class).cursorList(db).iterator();
                assertFalse(iterator.isClosed());

                try {
                    iterator.forEachRemaining(simpleModel -> {
                        assertEquals(String.valueOf(count[0]), simpleModel.name);
                        count[0]++;
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        iterator.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                assertTrue(iterator.isClosed());
                return null;
            }).execute(null, null, null, null);
            return null;
        });
    }

    @Test
    public void testCanIteratePartialList() {
        FlowManager.databaseForTable(SimpleModel.class, db -> {
            db.beginTransactionAsync((Function<DatabaseWrapper, Object>) databaseWrapper -> {
                for (int i = 0; i < 10; i++) {
                    FlowManager.getModelAdapter(SimpleModel.class).save(new SimpleModel(String.valueOf(i)), db);
                }
                return null;
            }).success((objectTransaction, o) -> {
                FlowCursorIterator<SimpleModel> iterator = SQLite.select().from(SimpleModel.class).cursorList(db).iterator(2, 7);
                final int[] count = {0};

                iterator.forEachRemaining(simpleModel -> {
                    assertEquals(String.valueOf(count[0] + 2), simpleModel.name);
                    count[0]++;
                });
                assertEquals(7, count[0]);
                return null;
            }).execute(null, null, null, null);
            return null;
        });
    }

    @Test
    public void testCanSupplyBadMaximumValue() {
        FlowManager.databaseForTable(SimpleModel.class, db -> {
            db.beginTransactionAsync((Function<DatabaseWrapper, Object>) databaseWrapper -> {
                for (int i = 0; i < 10; i++) {
                    FlowManager.getModelAdapter(SimpleModel.class).save(new SimpleModel(String.valueOf(i)), db);
                }
                return null;
            }).success((objectTransaction, o) -> {
                FlowCursorIterator<SimpleModel> iterator = SQLite.select().from(SimpleModel.class).cursorList(db).iterator(2, Long.MAX_VALUE);
                final int[] count = {0};

                iterator.forEachRemaining(simpleModel -> {
                    assertEquals(String.valueOf(count[0] + 2), simpleModel.name);
                    count[0]++;
                });
                assertEquals(8, count[0]);
                return null;
            }).execute(null, null, null, null);
            return null;
        });
    }
}
